package com.fasterxml.jackson.databind;

import com.fasterxml.jackson.databind.cfg.ConfigFeature;
import com.fasterxml.jackson.databind.exc.InvalidNullException;


public enum DeserializationFeature implements ConfigFeature {

    /**
     * 反序列化使用BIG_DECIMAL接收float
     */
    USE_BIG_DECIMAL_FOR_FLOATS(false),

    /**
     * 反序列化使用BIG_INTEGER接收int
     */
    USE_BIG_INTEGER_FOR_INTS(false),

    /**
     * 反序列化使用Long接收int
     */
    USE_LONG_FOR_INTS(false),

    /**
     * 在反序列化时，将 JSON 数组反序列化为 Java 数组。
     */
    USE_JAVA_ARRAY_FOR_JSON_ARRAY(false),

    /**
     * 在遇到未知属性时抛出异常。用于强制要求所有属性都应在对象定义中有对应的字段或 setter 方法。
     */
    FAIL_ON_UNKNOWN_PROPERTIES(true),

    /**
     * 在原始类型的属性为 null 时抛出异常。用于确保原始类型不为 null。
     */
    FAIL_ON_NULL_FOR_PRIMITIVES(false),

    /**
     * 在枚举类型的属性为数值类型（如整数）时抛出异常。用于确保枚举类型的属性只能是字符串类型。
     */
    FAIL_ON_NUMBERS_FOR_ENUMS(false),

    /**
     * 在找不到合适的子类型时抛出异常。用于确保在反序列化时能够正确匹配子类型。
     */
    FAIL_ON_INVALID_SUBTYPE(true),

    /**
     * 在读取重复的树节点键时抛出异常。用于确保树形结构中每个键都是唯一的。
     */
    FAIL_ON_READING_DUP_TREE_KEY(false),

    /**
     * 在忽略属性时抛出异常。用于检测是否有未处理的属性。
     */
    FAIL_ON_IGNORED_PROPERTIES(false),

    /**
     * 如果JSON字符串中包含某个对象没有对应的字段或属性，并且没有任何setter或handler来处理这种情况，那么默认行为是抛出异常。
     */
    FAIL_ON_UNRESOLVED_OBJECT_IDS(true),

    /**
     * 在缺少构造器参数时抛出异常。用于确保所有构造器参数都能被正确初始化。
     */
    FAIL_ON_MISSING_CREATOR_PROPERTIES(false),

    /**
     * 在构造器参数为 null 时抛出异常。用于确保构造器参数不为 null。
     */
    FAIL_ON_NULL_CREATOR_PROPERTIES(false),

    /**
     * 当你在使用 Jackson 进行 JSON 反序列化时，如果你的 JSON 数据中包含了用于指示具体类型的字段（例如，使用了 @class 属性来表示具体的类型），
     * Jackson 需要知道如何处理这个字段。如果没有配置相应的处理策略，当这个字段缺失时，Jackson 可能无法正确地确定对象的类型，进而可能导致反序列化失败。
     */
    FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY(true),

    /**
     * 如果存在额外的标记，即使这些标记并不影响JSON对象的主要结构，Jackson也会抛出异常，因为这违反了JSON格式的正确性。
     * 这种行为有助于确保数据的完整性和正确性，避免因为末尾的额外标记导致的潜在错误。
     */
    FAIL_ON_TRAILING_TOKENS(false),

    /**
     * 将解析过程中发生的异常封装为 Jackson 运行时异常，而不是普通的 IOException
     */
    WRAP_EXCEPTIONS(true),

    /**
     * 允许将单一值反序列化为数组。当遇到单一值时，将其解析为只包含该值的数组。
     */
    ACCEPT_SINGLE_VALUE_AS_ARRAY(false),

    /**
     * 允许在反序列化数组时解包单个元素。当数组仅包含一个元素时，返回该元素而不是数组。
     */
    UNWRAP_SINGLE_VALUE_ARRAYS(false),

    /**
     * 允许解包根对象，将根对象的属性直接提取为反序列化的结果。
     */
    UNWRAP_ROOT_VALUE(false),

    /**
     * 允许将空字符串反序列化为 null 对象。当遇到空字符串时，解析为 null。
     */
    ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false),

    /**
     * 允许将空数组（[]）反序列化为 null 对象。当遇到空数组时，解析为 null。
     */
    ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false),

    /**
     * 允许将浮点数作为整数进行反序列化。当遇到浮点数时，如果它表示一个整数，则解析为整数
     */
    ACCEPT_FLOAT_AS_INT(true),

    /**
     * 使用toString()方法获取枚举值的字符串形式
     */
    READ_ENUMS_USING_TO_STRING(false),

    /**
     * 将未知的枚举值反序列化为 null
     */
    READ_UNKNOWN_ENUM_VALUES_AS_NULL(false),

    /**
     * 当反序列化枚举时，如果遇到未知的枚举值，将使用枚举的默认值。
     */
    READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE(false),

    /**
     * 将时间戳解析为纳秒
     */
    READ_DATE_TIMESTAMPS_AS_NANOSECONDS(true),

    /**
     * 在反序列化过程中调整日期时间值到上下文时区
     */
    ADJUST_DATES_TO_CONTEXT_TIME_ZONE(true),

    /**
     * 决定是否立即获取序列化器,使用缓存
     * EAGER_SERIALIZER_FETCH的设置取决于应用的具体需求和性能与内存使用的权衡。
     * 如果应用对性能有较高要求，且能够接受一定的内存增加，那么设置为true可能是合适的。
     * 反之，如果更注重内存使用的效率，或者对性能要求不是特别高，那么可以考虑保持默认设置或根据具体情况进行调整‌
     */
    EAGER_DESERIALIZER_FETCH(true);

    private final boolean _defaultState;
    private final int _mask;

    private DeserializationFeature(boolean defaultState) {
        _defaultState = defaultState;
        _mask = (1 << ordinal());
    }

    @Override
    public boolean enabledByDefault() {
        return _defaultState;
    }

    @Override
    public int getMask() {
        return _mask;
    }

    @Override
    public boolean enabledIn(int flags) {
        return (flags & _mask) != 0;
    }
}
